package com.onesports.intelligent.k12.polarlight.controller.wx.user;

import com.onesports.intelligent.k12.polarlight.cache.RedisTokenProvider;
import com.onesports.intelligent.k12.polarlight.common.errors.exceptions.BusinessException;
import com.onesports.intelligent.k12.polarlight.common.utils.ResultUtil;
import com.onesports.intelligent.k12.polarlight.constant.ApiPathConstants;
import com.onesports.intelligent.k12.polarlight.constant.BizConstants;
import com.onesports.intelligent.k12.polarlight.constant.CacheConstants;
import com.onesports.intelligent.k12.polarlight.domain.dto.wx.UserNameAvaDTO;
import com.onesports.intelligent.k12.polarlight.domain.entity.organization.Coach;
import com.onesports.intelligent.k12.polarlight.domain.entity.sys.WxUser;
import com.onesports.intelligent.k12.polarlight.domain.entity.sys.WxUserPurse;
import com.onesports.intelligent.k12.polarlight.domain.vo.user.WxUserDetailVO;
import com.onesports.intelligent.k12.polarlight.domain.vo.wx.OrganizationCampusApplyVO;
import com.onesports.intelligent.k12.polarlight.security.DomainUserDetails;
import com.onesports.intelligent.k12.polarlight.security.SecurityUtils;
import com.onesports.intelligent.k12.polarlight.security.jwt.JwtTokenProvider;
import com.onesports.intelligent.k12.polarlight.security.wx.WxAuthenticationToken;
import com.onesports.intelligent.k12.polarlight.security.wx.WxLoginSuccessHandler;
import com.onesports.intelligent.k12.polarlight.service.coach.CoachService;
import com.onesports.intelligent.k12.polarlight.service.student.WxUserService;
import com.onesports.intelligent.k12.polarlight.service.wx.WxUserPurseService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;

/**
 * @author wujinjie
 */
@Api(tags = "会员端-我的")
@RestController
@RequiredArgsConstructor
@PreAuthorize("hasAuthority('MINI_APP')")
@RequestMapping(ApiPathConstants.WX_USER_CENTER)
public class WxUserController {

    private final WxUserService wxUserService;

    private final WxUserPurseService wxUserPurseService;

    private final CoachService coachService;

    private final JwtTokenProvider jwtTokenProvider;

    private final RedisTokenProvider redisTokenProvider;

    private final CacheManager cacheManager;

    @GetMapping("/detail")
    @ApiOperation(value = "当前登录用户学生集合")
    @PreAuthorize("hasAnyAuthority('MINI_APP','MINI_APP_COACH')")
    public ResponseEntity<WxUserDetailVO> detail() {
        String accountId = SecurityUtils.getAccountId();
        WxUser user = wxUserService.getById(accountId);
        WxUserPurse wxUserPurse = wxUserPurseService.getMyPurse(user.getId());
        WxUserDetailVO wxUserDetailVO = new WxUserDetailVO();
        wxUserDetailVO.setName(user.getNickname());
        wxUserDetailVO.setAvatar(user.getAvatar());
        wxUserDetailVO.setRemainingSum(wxUserPurse.getAllowAmount());
        SecurityUtils.getCurrentUserDetails().get().isCoach();
        if (SecurityUtils.isCoach()) {
            wxUserDetailVO.setRoleName("教练");
        } else {
            wxUserDetailVO.setRoleName("家长");
        }
        return ResultUtil.success(wxUserDetailVO);
    }

    @GetMapping("/get-apply")
    @ApiOperation(value = "我的申报")
    public ResponseEntity<List<OrganizationCampusApplyVO>> getApply() {
        return ResultUtil.success(this.wxUserService.getApply());
    }


    @GetMapping("/role-switching")
    @ApiOperation(value = "切换角色")
    @PreAuthorize("isAuthenticated()")
    public ResponseEntity<WxLoginSuccessHandler.LoginVO> roleSwitching() {
        String token;
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        String wxUserId = SecurityUtils.getAccountId();
        //当前登录是教练还是家长
        boolean isCoach = SecurityUtils.isCoach();
        String coachId = "";
        if (isCoach) {
            //切换成家长
            grantedAuthorities.add(new SimpleGrantedAuthority(BizConstants.ROLE_MINI_APP));
        } else {
            //切换成教练
            Coach coach = coachService.getByWxUserId(wxUserId);
            if (coach == null) {
                throw new BusinessException("查无其他角色");
            }
            if (!coach.getStatus()) {
                throw new BusinessException("教练账号已禁用");
            }
            coachId = coach.getId();
            grantedAuthorities.add(new SimpleGrantedAuthority(BizConstants.ROLE_MINI_APP_COACH));
        }

        DomainUserDetails userDetails =
                DomainUserDetails.builder()
                        .username(SecurityUtils.getPhone())
                        .current(wxUserId)
                        .phone(SecurityUtils.getPhone())
                        .nickname(SecurityUtils.getNickname())
                        .authorities(grantedAuthorities)
                        .coach(!isCoach)
                        .coachId(coachId)
                        .build();
        WxAuthenticationToken authentication = new WxAuthenticationToken(userDetails, grantedAuthorities);
        if (!isCoach) {
            token = redisTokenProvider.createToken(authentication, RedisTokenProvider.TOKEN_PREFIX_COACH, false);
        } else {
            token = jwtTokenProvider.createToken(authentication, null, false);
            Cache tokenCache = cacheManager.getCache(CacheConstants.TOKEN);
            if (tokenCache != null) {
                String outdatedToken = tokenCache.get(SecurityUtils.getCoachId(), String.class);
                if (StringUtils.isNotEmpty(outdatedToken)) {
                    redisTokenProvider.removeToken(outdatedToken);
                }
            }
        }
        WxLoginSuccessHandler.LoginVO loginVO =
                WxLoginSuccessHandler.LoginVO.builder()
                        .accessToken(token)
                        .nickname(userDetails.getNickname())
                        .phone(userDetails.getPhone())
                        .isCoach(!isCoach)
                        .build();
        return ResultUtil.success(loginVO);
    }

    @PreAuthorize("hasAnyAuthority('MINI_APP','MINI_APP_COACH')")
    @PostMapping("/update")
    @ApiOperation(value = "修改当前用户信息")
    public ResponseEntity<String> detail(@Valid @RequestBody UserNameAvaDTO dto) {
        return wxUserService.updateUserNickName(dto) ? ResultUtil.success("修改成功") : ResultUtil.success("修改失败");
    }

}
